package com.bjpowernode.web.controller;

import com.bjpowernode.web.Result;
import com.bjpowernode.commons.constants.RedisKey;
import com.bjpowernode.commons.constants.Reg;
import com.bjpowernode.commons.exception.YLBException;
import com.bjpowernode.commons.model.User;
import com.bjpowernode.commons.service.UserService;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("user")
@CrossOrigin
public class UserController {
    @DubboReference
    private UserService userService;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private ObjectMapper objectMapper;

    @GetMapping("auth/{idcard}/{name}")
    public Map auth(@PathVariable String idcard, @PathVariable String name,
                    @RequestHeader(value = "token", required = false) String token) throws Exception {
        /*Map params = new HashMap();
        params.put("idcard", idcard);
        params.put("name", name);
        params.put("appkey", "c095dc078963bd2660acb657550478bd");
        String result = HttpClientUtils.doGet("https://way.jd.com/lundear/idcard", params);

        Auth auth = objectMapper.readValue(result, Auth.class);
        // 认证结果：0：匹配成功，1：姓名和身份证不匹配，2：身份证不存在
        Integer code = (Integer) auth.getResult().get("code");*/

        int code = 0;
        if (code == 0) {
            // 同步数据库
            User user = (User) redisTemplate.opsForValue().get(token);
            userService.auth(user.getId(), name, idcard);

            // 更新redis中的User数据
            user.setName(name);
            user.setIdCard(idcard);
            redisTemplate.opsForValue().set(token, user, 30, TimeUnit.MINUTES);
        } else {
            throw new YLBException("姓名和身份证不匹配，请检查！");
        }

        return Result.SUC;
    }

    @PostMapping("login2")
    public Map login2(String phone, String code, HttpSession session) {
        String key = String.format(RedisKey.SMS_LOGIN, phone);
        String realCode = (String) redisTemplate.opsForValue().get(key);
        if (realCode == null || !realCode.equals(code)) {
            throw new YLBException("验证码不正确！");
        }

        User user = userService.login(phone);

        // 将用户对象保存到 session 中，以便后续判断是否登录或获取用户信息
        session.setAttribute("loginUser", user);

        Map map = new HashMap();
        map.put("success", true);
        boolean auth = user.getName() != null && !user.getName().equals("");
        map.put("auth", auth);

        return map;
    }

    @RequestMapping("login")
    public Map login(String phone, String password) {
        User user = userService.login(phone, password);

        // 更新登录时间
        userService.updateLoginTime(user.getId(), new Date());

        // 生成客户端的唯一标识token（令牌）
        String token = UUID.randomUUID().toString().replace("-", "").toUpperCase();
        // 如何保证在用户有操作(向服务器发送请求)的情况下，重置失效时间为30分钟
        // 提示，重置时间的方法：redisTemplate.expire(token, 30, TimeUnit.MINUTES);
        redisTemplate.opsForValue().set(token, user, 30, TimeUnit.MINUTES);
        redisTemplate.expire(token, 30, TimeUnit.MINUTES);

        Map map = new HashMap();
        map.put("success", true);
        boolean auth = user.getName() != null && !user.getName().equals("");
        map.put("auth", auth);
        map.put("token", token);
        map.put("loginUser", user);
        return map;
    }

    @GetMapping("checkLogin")
    public boolean checkLoginStatus(@RequestHeader(value = "token", required = false) String token) {
        if (StringUtils.isBlank(token)) {
            return false;
        }
        if (redisTemplate.opsForValue().get(token) == null) {
            return false;
        }
        return true;
    }

    @GetMapping("checkPhone")
    public boolean checkPhone(String phone) {
        return userService.checkPhone(phone);
    }


    @PostMapping("register")
    public Map register(String phone, String password, String code) {
        // 数据验证
        checkData(phone, password, code);

        userService.register(phone, password);

        return Result.SUC;
    }

    private void checkData(String phone, String password, String code) {

        if (phone == null || "".equals(phone)) {
            throw new YLBException("手机号不能为空！");
        }
        if (!phone.matches(Reg.PHONE)) {
            throw new YLBException("手机格式不正确！");
        }

        if (password == null || "".equals(password)) {
            throw new YLBException("密码不能为空！");
        }
        if (!password.matches(Reg.PWD)) {
            throw new YLBException("密码必须是6-20位，且同时包含大、小写字母、数字、特殊符号！");
        }

        String key = String.format(RedisKey.SMS_REG, phone);
        String realCode = (String) redisTemplate.opsForValue().get(key);
        // 验证码超时或错误
        if (realCode == null || !realCode.equals(code)) {
            throw new YLBException("验证码不正确！");
        }
    }

}
